package org.yacon;

import java.util.*;

/**
 * Class represents parameter of the ConsoleCommand. It contains links on inner parameters.
 *
 * @author Evgeny Vetrov
 * @see ConsoleCommand
 */
class CommandParameter
{
    private final Map<String, Set<CommandParameter>> params;
    private final String name;
    private final String description;
    private final boolean required;
    private final String type;
    private final String pattern;

    /**
     * Creates CommandParameter with name & inner parameters specified
     *
     * @param name        name of command parameter, can't be null
     * @param params      inner parameters of this parameter. If inner parameters contains <bold>switch</bold> then a
     *                    <code>key</code> of the map is value of <bold>case</bold> and <code>value</code> of map
     *                    is set of inner parameters of case. For non-switch inner parameters <code>null</null>
     *                    is used as key, and set of all non-switch parameters as value
     * @param description parameter description
     * @param required    <code>true</code> if parameter is required
     * @param pattern     parameter pattern
     * @param type        parameter type
     */
    private CommandParameter(String name, Map<String, Set<CommandParameter>> params, String description,
                             boolean required, String pattern, String type)
    {
        if (name == null || name.length() == 0)
            throw new IllegalArgumentException("parameter name can't be null");
        this.name = name;
        this.pattern = pattern;
        this.type = type;
        HashMap<String, Set<CommandParameter>> copy = new HashMap<String, Set<CommandParameter>>();
        for (Map.Entry<String, Set<CommandParameter>> entry : params.entrySet())
            copy.put(entry.getKey(), Collections.unmodifiableSet(new HashSet<CommandParameter>(entry.getValue())));
        this.params = Collections.unmodifiableMap(copy);
        this.description = description;
        this.required = required;
    }

    static class Builder
    {
        private Map<String, Set<CommandParameter>> params;
        private String name;
        private String description;
        private boolean required;
        private String type;
        private String pattern;


        private Builder()
        {
        }

        static Builder create(String name, Map<String, Set<CommandParameter>> params)
        {
            Builder builder = new Builder();
            builder.name = name;
            builder.params = params;
            return builder;
        }

        Builder setDescription(String description)
        {
            this.description = description;
            return this;
        }

        Builder setRequired(boolean required)
        {
            this.required = required;
            return this;
        }

        Builder setType(String type)
        {
            this.type = type;
            return this;
        }

        Builder setPattern(String pattern)
        {
            this.pattern = pattern;
            return this;
        }

        CommandParameter build()
        {
            return new CommandParameter(name, params, description, required, pattern, type);
        }
    }

    Map<String, Set<CommandParameter>> getParams()
    {
        return params;
    }

    String getName()
    {
        return name;
    }

    String getDescription()
    {
        return description;
    }

    boolean isRequired()
    {
        return required;
    }

    String getType()
    {
        return type;
    }

    String getPattern()
    {
        return pattern;
    }
}
